home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1273.dms / var1273.adf / AmiCDROM / main.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  27KB  |  950 lines

  1. /* main.c:
  2.  *
  3.  * Interactive test program for the ISO- and Rock-Ridge-support
  4.  * routines.
  5.  *
  6.  * ----------------------------------------------------------------------
  7.  * This code is (C) Copyright 1993 by Frank Munkert.
  8.  * All rights reserved.
  9.  * This software may be freely distributed and redistributed for
  10.  * non-commercial purposes, provided this notice is included.
  11.  * ----------------------------------------------------------------------
  12.  * History:
  13.  * 
  14.  * 28-Nov-93   fmu   Improved "cdrom d" command.
  15.  * 12-Oct-93   fmu   "Show path table" function removed.
  16.  * 09-Oct-93   fmu   Open utility.library.
  17.  */
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22.  
  23. #include <dos/var.h>
  24. #include <clib/dos_protos.h>
  25. #include <clib/exec_protos.h>
  26.  
  27. #include "cdrom.h"
  28. #include "iso9660.h"
  29. #include "rock.h"
  30. #include "hfs.h"
  31.  
  32. #ifdef AZTEC_C
  33. #include <pragmas/dos_lib.h>
  34. #include <pragmas/exec_lib.h>
  35. #endif
  36.  
  37. #ifdef LATTICE
  38. #include <pragmas/dos_pragmas.h>
  39. #include <pragmas/exec_pragmas.h>
  40. #endif
  41.  
  42. #if defined(_DCC) && defined(REGISTERED)
  43. #include <pragmas/dos_pragmas.h>
  44. #include <pragmas/exec_pragmas.h>
  45. extern struct Library *SysBase, *DOSBase;
  46. #endif
  47.  
  48. #define STD_BUFFERS 10
  49. #define FILE_BUFFERS 5
  50.  
  51. #ifdef DEBUG_SECTORS
  52. void dbprintf (char *p_dummy, ...)
  53. {
  54. }
  55. #endif
  56.  
  57. CDROM *cd = NULL;
  58. char g_the_device[80];
  59. int g_the_unit;
  60. int g_trackdisk = 0;
  61. int g_fastmem = 0;
  62.  
  63. struct Library *UtilityBase;
  64.  
  65. void Cleanup (void)
  66. {
  67.   if (cd)
  68.     Cleanup_CDROM (cd);
  69.  
  70.   if (UtilityBase)
  71.     CloseLibrary (UtilityBase);
  72. }
  73.  
  74. void Usage (void)
  75. {
  76.   fprintf (stderr,
  77.     "Usage: cdrom command [parameters]\n"
  78.     "Commands:\n"
  79.     "  a             Show information on CDROM drive\n"
  80.     "  b             Read table of contents\n"
  81.     "  c name        Show contents of file 'name'\n"
  82.     "  d[rl] dir     Show contents of directory 'dir' (use ISO names)\n"
  83.     "                r=also show subdirectories, l=show additional information\n"
  84.     "  e[rl] dir     Show contents of directory 'dir' (use Rock Ridge names)\n"
  85.     "                r=also show subdirectories, l=show additional information\n"
  86.     "  f dir name    Change to directory 'dir' and try to find object 'name'\n"
  87.     "  i             Check which protocol is used\n"
  88.     "  j [01]        0=start audio, 1=stop motor\n"
  89.     "  m num         Read catalog node 'num' (MacHFS only)\n"
  90.     "  o name        Try to open object 'name'\n"
  91.     "  r             Read contents of root directory\n"
  92.     "  s num [cnt]   Read 'cnt' sectors, starting at sector 'num'\n"
  93.     "  t name        Try to open parent of object 'name'\n"
  94.     "  v             Read primary volume descriptor\n"
  95.     "  x [01]        Select mode: 0=normal, 1=XA (for Toshiba 3401)\n"
  96.     "  z             Send test unit ready command\n"
  97.     "Use \":\" as the name of the root directory\n"
  98.     );
  99.   exit (1);
  100. }
  101.  
  102. char *MKSTR (char *p_in, int p_length, char *p_out)
  103. {
  104.   char *res = p_out;
  105.   int len = p_length;
  106.   int i;
  107.   
  108.   while (len && p_in[len-1] == ' ')
  109.     len--;
  110.  
  111.   for (i=0; i<len; i++)
  112.     *p_out++ = *p_in++;
  113.     
  114.   *p_out = 0;
  115.   
  116.   return res;
  117. }
  118.  
  119. void Show_Flags (unsigned char p_flags)
  120. {
  121.   if (p_flags & 1)
  122.     printf ("existence ");
  123.   if (p_flags & 2)
  124.     printf ("directory ");
  125.   if (p_flags & 4)
  126.     printf ("associated ");
  127.   if (p_flags & 8)
  128.     printf ("record ");
  129.   if (p_flags & 16)
  130.     printf ("protection ");
  131.   if (p_flags & 128)
  132.     printf ("multi-extent ");
  133. }
  134.  
  135. void Show_Directory_Record (directory_record *p_dir)
  136. {
  137.   char buf[256];
  138.  
  139.   printf ("Extended Attr Record Length: %d\n", (int) p_dir->ext_attr_length);
  140.   printf ("Location of Extent:          %lu\n", p_dir->extent_loc_m);
  141.   printf ("Data Length:                 %lu\n", p_dir->data_length_m);
  142.   printf ("Recording Date and Time:     %02d.%02d.19%02d %02d:%02d:%02d %+d\n",
  143.         (int) p_dir->day, (int) p_dir->month, (int) p_dir->year,
  144.       (int) p_dir->hour, (int) p_dir->minute, (int) p_dir->second,
  145.       (int) p_dir->tz);
  146.   printf ("Flags:                       %d (", (int) p_dir->flags);
  147.   Show_Flags (p_dir->flags);
  148.   printf (")\n");
  149.   printf ("File Unit Size:              %d\n", (int) p_dir->file_unit_size);
  150.   printf ("Gap Size:                    %d\n", (int) p_dir->gap_size);
  151.   printf ("Volume Sequence Number:      %hu\n", p_dir->sequence_m);
  152.   printf ("File Identifier:             ");
  153.   if (p_dir->file_id[0] == 0)
  154.     printf ("(00)\n");
  155.   else if (p_dir->file_id[0] == 1)
  156.     printf ("(01)\n");
  157.   else
  158.     printf ("%s\n", MKSTR (p_dir->file_id, p_dir->file_id_length, buf));
  159. }
  160.  
  161. void Find_Block_Starting_With (CDROM *p_cd, int p_val)
  162. {
  163.   unsigned long sec = 0;
  164.   int cmp;
  165.   int i;
  166.   
  167.   for (;;) {
  168.     if (!Read_Sector (p_cd, sec)) {
  169.       fprintf (stderr, "cannot read sector 16\n");
  170.       exit (1);
  171.     }
  172.     for (i=0; i<4; i++) {
  173.       cmp = p_cd->buffer[i<<9] * 256 + p_cd->buffer[(i<<9)+1];
  174.       if (cmp == p_val)
  175.         printf ("sector %lu, block %d\n", sec, i);
  176.     }
  177.     sec++;
  178.   }
  179. }
  180.  
  181. void Show_Primary_Volume_Descriptor (CDROM *p_cd)
  182. {
  183.   prim_vol_desc *pvd;
  184.   char buf[129];
  185.   int blk;
  186.   t_mdb mdb;
  187.   t_hdr_node hdr;
  188.   int skip;
  189.   int protocol;
  190.   t_bool hfs;
  191.   
  192.   hfs = Uses_HFS_Protocol (p_cd, &skip);
  193.   protocol = Which_Protocol (p_cd, TRUE, &skip);
  194.   
  195.   if (protocol == PRO_UNKNOWN) {
  196.     printf ("Unknown protocol");
  197.     return;
  198.   }
  199.   
  200.   if (protocol == PRO_HIGH_SIERRA) {
  201.     printf ("High sierra protocol (not supported)\n");
  202.   }
  203.   
  204.   if ((protocol == PRO_ROCK || protocol == PRO_ISO) && hfs)
  205.     printf ("Multi-platform disk: HFS & ISO\n");
  206.  
  207.   if (protocol == PRO_ROCK)
  208.     printf ("Rock Ridge extensions available\n");
  209.   
  210.   if (protocol == PRO_ISO || protocol == PRO_ROCK) {
  211.  
  212.     if (!Read_Sector (p_cd, 16)) {
  213.       fprintf (stderr, "cannot read sector 16\n");
  214.       exit (1);
  215.     }
  216.  
  217.     pvd = (prim_vol_desc *) p_cd->buffer;
  218.     printf ("--- ISO-9600: ---\n");
  219.     printf ("Volume Descriptor Type:          %d\n", (int) pvd->type);
  220.     printf ("Standard Identifier:             %s\n", pvd->id);
  221.     printf ("Volume Descriptor Version:       %d\n", (int) pvd->version);
  222.     printf ("System Identifier:               %s\n", MKSTR (pvd->system_id,32,buf));
  223.     printf ("Volume Identifier:               %s\n", MKSTR (pvd->volume_id,32,buf));
  224.     printf ("Volume Space Size:               %lu\n", pvd->space_size_m);
  225.     printf ("Volume Set Size:                 %hu\n", pvd->set_size_m);
  226.     printf ("Volume Sequence Number:          %hu\n", pvd->sequence_m);
  227.     printf ("Logical Block Size:              %hu\n", pvd->block_size_m);
  228.     printf ("Path Table Size:                 %lu\n", pvd->path_size_m);
  229.     printf ("Location of Occ of M Path Table: %lu\n", pvd->m_table); 
  230.     printf ("Location of Occ of Opt M Path T: %lu\n", pvd->opt_m_table);
  231.     printf ("Volume Set Identifier:           %s\n",
  232.                       MKSTR (pvd->volume_set_id,128,buf));  
  233.     printf ("Publisher Identifier:            %s\n",
  234.                       MKSTR (pvd->publisher_id,128,buf)); 
  235.     printf ("Data Preparer Identifier:        %s\n",
  236.                       MKSTR (pvd->data_preparer,128,buf));
  237.     printf ("Application Identifier:          %s\n",
  238.                       MKSTR (pvd->application_id,128,buf));
  239.     printf ("Copyright File Identifier:       %s\n",
  240.                       MKSTR (pvd->copyright,37,buf));
  241.     printf ("Abstract File Identifier:        %s\n",
  242.                       MKSTR (pvd->abstract_file_id,37,buf));
  243.     printf ("Bibliographic File Identifier:   %s\n",
  244.                       MKSTR (pvd->bibliographic_id,37,buf));
  245.     printf ("File Structure Version:          %d\n",
  246.                       (int) pvd->file_structure_version);
  247.     printf ("ROOT DIRECTORY RECORD:\n");
  248.     Show_Directory_Record (&pvd->root);
  249.   }
  250.   
  251.   if (hfs) {
  252.     if ((blk = HFS_Find_Master_Directory_Block (p_cd, &mdb)) < 0) {
  253.       printf ("No master directory block found\n");
  254.       exit (1);
  255.     }
  256.     printf ("--- MacHFS: ---\n");
  257.     printf ("Master directory block located at block %d\n", blk);
  258.     printf ("Volume signature:               0x%hx\n", mdb.SigWord);
  259.     printf ("Date/Time of creation:          %lu\n", mdb.CrDate);
  260.     printf ("Date/Time of last modification: %lu\n", mdb.LsMod);
  261.     printf ("Volume attributes:              0x%hx\n", mdb.Atrb);
  262.     printf ("Number of files in root dir:    %u\n", mdb.NmFls);
  263.     printf ("Allocation block size:          %lu bytes\n", mdb.AlBlkSiz);
  264.     printf ("Loc of first allocation block:  %u\n", mdb.AlBlSt);
  265.     printf ("Volume name:                    %s\n",
  266.                     MKSTR ((char *) mdb.VolName, mdb.VolNameLen,buf));
  267.     printf ("Number of files in volume:      %lu\n", mdb.FilCnt);
  268.     printf ("Number of dirs in volume:       %lu\n", mdb.DirCnt);
  269.     printf ("Size of catalog file:           %lu allocation blocks\n",
  270.                             mdb.CTFlSize);
  271.     printf ("Extent record for catalog file:\n");
  272.     printf ("  1. allocation block: %10lu   length: %10lu\n",
  273.                     mdb.CTExtRec[0].StABN, mdb.CTExtRec[0].NumABlks);
  274.     printf ("  2. allocation block: %10lu   length: %10lu\n",
  275.                     mdb.CTExtRec[1].StABN, mdb.CTExtRec[1].NumABlks);
  276.     printf ("  3. allocation block: %10lu   length: %10lu\n",
  277.                     mdb.CTExtRec[2].StABN, mdb.CTExtRec[2].NumABlks);
  278.     if (!HFS_Get_Header_Node (p_cd, blk, &mdb, &hdr))
  279.       printf ("*** Cannot read header node!!!\n");
  280.     printf ("Header node:\n");
  281.     printf ("Depth of tree:                  %u\n", hdr.Depth);
  282.     printf ("Number of root node:            %lu\n", hdr.Root);
  283.     printf ("Number of leaf records in tree: %lu\n", hdr.NRecs);
  284.     printf ("Number of first leaf node:      %lu\n", hdr.FNode);
  285.     printf ("Number of last leaf node:       %lu\n", hdr.LNode);
  286.   }
  287. }
  288.  
  289. void Show_Directory (CDROM *p_cd, unsigned long p_location, unsigned long p_length)
  290. {
  291.   int cnt = 0;
  292.   int pos = 0;
  293.   
  294.   if (!Read_Sector (p_cd, p_location)) {
  295.     fprintf (stderr, "cannot read sector %lu\n", p_location);
  296.     exit (1);
  297.   }
  298.  
  299.   while (cnt < p_length) {
  300.     directory_record *dir = (directory_record *) (p_cd->buffer + pos);
  301.     
  302.     if (dir->length == 0)
  303.       break;
  304.     Show_Directory_Record (dir);
  305.     cnt += dir->length;
  306.     pos += dir->length;
  307.     if (cnt < p_length) {
  308.       printf ("------------------------------------------------------------\n");
  309.       if (pos >= 2048) {
  310.         if (!Read_Sector (p_cd, ++p_location)) {
  311.           fprintf (stderr, "cannot read sector %lu\n", p_location);
  312.           exit (1);
  313.         }
  314.         pos = 0;
  315.       }
  316.     }
  317.   }
  318. }
  319.  
  320. void Show_Root_Directory (CDROM *p_cd)
  321. {
  322.   prim_vol_desc *pvd;
  323.   
  324.   if (!Read_Sector (p_cd, 16)) {
  325.     fprintf (stderr, "cannot read sector 16\n");
  326.     exit (1);
  327.   }
  328.  
  329.   pvd = (prim_vol_desc *) p_cd->buffer;
  330.  
  331.   Show_Directory (p_cd, pvd->root.extent_loc_m, pvd->root.data_length_m);
  332. }
  333.  
  334. void Check_Protocol (CDROM *p_cd)
  335. {
  336.   int skip;
  337.  
  338.   switch (Which_Protocol (p_cd, TRUE, &skip)) {
  339.   case PRO_ROCK:
  340.     printf ("Rock Ridge protocol, skip length = %d\n", skip);
  341.     break;
  342.   case PRO_ISO:
  343.     printf ("ISO-9660 protocol\n");
  344.     break;
  345.   case PRO_HFS:
  346.     printf ("Macintosh HFS protocol\n");
  347.     break;
  348.   case PRO_HIGH_SIERRA:
  349.     printf ("High Sierra protocol\n");
  350.     break;
  351.   default:
  352.     printf ("Unknown protocol, iso_errno = %d\n", iso_errno);
  353.     break;
  354.   }
  355. }
  356.  
  357. void Try_To_Open (CDROM *p_cd, char *p_directory, char *p_name)
  358. {
  359.   VOLUME *vol;
  360.   CDROM_OBJ *top = NULL;
  361.   CDROM_OBJ *home;
  362.   CDROM_OBJ *obj;
  363.   CDROM_OBJ *parent;
  364.  
  365.   if (!(vol = Open_Volume (p_cd, 1))) {
  366.     fprintf (stderr, "cannot open volume; iso_errno = %d\n", iso_errno);
  367.     exit (1);
  368.   }
  369.  
  370.   if (p_directory && p_directory != (char *) -1) {
  371.     if (!(top = Open_Top_Level_Directory (vol))) {
  372.       fprintf (stderr, "cannot open top level directory\n");
  373.       Close_Volume (vol);
  374.       exit (1);
  375.     }
  376.     
  377.     if (!(home = Open_Object (top, p_directory))) {
  378.       fprintf (stderr, "cannot open top level directory\n");
  379.       Close_Object (top);
  380.       Close_Volume (vol);
  381.       exit (1);
  382.     }
  383.   } else {
  384.     if (!(home = Open_Top_Level_Directory (vol))) {
  385.       fprintf (stderr, "cannot open home directory;"
  386.                        " iso_errno = %d\n", iso_errno);
  387.       Close_Volume (vol);
  388.       exit (1);
  389.     }
  390.   }
  391.  
  392.   if (obj = Open_Object (home, p_name)) {
  393.     CDROM_INFO info;
  394.     printf ("%s '%s' found, location = %lu\n",
  395.             obj->directory_f ? "Directory" : "File",
  396.             p_name, Location (obj));
  397.     if (CDROM_Info (obj, &info)) {
  398.       printf ("INFO Name = ");
  399.       fwrite (info.name, info.name_length, 1, stdout);
  400.       printf ("\n");
  401.     } else
  402.       printf ("CANNOT FIND INFO FOR OBJECT!\n");
  403.     if (p_directory == (char *) -1) {
  404.       parent = Find_Parent (obj);
  405.       if (parent) {
  406.         printf ("parent found, location = %lu\n",
  407.             Location (parent));
  408.         Close_Object (parent);
  409.       } else
  410.         printf ("parent not found, iso_errno = %d\n", iso_errno);
  411.     }
  412.     Close_Object (obj);
  413.   } else {
  414.     if (iso_errno == ISOERR_NOT_FOUND)
  415.       printf ("Object '%s' not found\n", p_name);
  416.     else
  417.       printf ("Object '%s': iso_errno = %d\n", p_name, iso_errno);
  418.   }
  419.  
  420.   if (top)
  421.     Close_Object (top);
  422.   Close_Object (home);
  423.   Close_Volume (vol);
  424. }
  425.  
  426. void Show_File_Contents (CDROM *p_cd, char *p_name)
  427. {
  428.   VOLUME *vol;
  429.   CDROM_OBJ *home;
  430.   CDROM_OBJ *obj;
  431. #define THEBUFSIZE 99
  432.   char buffer[THEBUFSIZE];
  433.   int cnt;
  434.  
  435.   if (!(vol = Open_Volume (p_cd, 1))) {
  436.     fprintf (stderr, "cannot open volume; iso_errno = %d\n", iso_errno);
  437.     exit (1);
  438.   }
  439.  
  440.   if (!(home = Open_Top_Level_Directory (vol))) {
  441.     fprintf (stderr, "cannot open top level directory;"
  442.                      " iso_errno = %d\n", iso_errno);
  443.     Close_Volume (vol);
  444.     exit (1);
  445.   }
  446.  
  447.   if (obj = Open_Object (home, p_name)) {
  448.     for (;;) {
  449.       cnt = Read_From_File (obj, buffer, THEBUFSIZE);
  450.       if (cnt == -1) {
  451.         fprintf (stderr, "cannot read from file!\n");
  452.     break;
  453.       }
  454.       if (cnt == 0)
  455.         break;
  456.       fwrite (buffer, cnt, 1, stdout);
  457.     }
  458.  
  459.     Close_Object (obj);
  460.   } else {
  461.     fprintf (stderr, "Object '%s': iso_errno = %d\n", p_name, iso_errno);
  462.   }
  463.  
  464.   Close_Object (home);
  465.   Close_Volume (vol);
  466.   
  467. }
  468.  
  469. void Print_System_Use_Fields (CDROM *p_cd, directory_record *p_dir,
  470.                   int p_skip_size)
  471. {
  472.   int system_use_pos;
  473.   int slen;
  474.   unsigned long length = p_dir->length;
  475.   unsigned char *buf = (unsigned char *) p_dir;
  476.  
  477.   printf ("   system use fields: ");
  478.  
  479.   system_use_pos = 33 + p_dir->file_id_length;
  480.   if (system_use_pos & 1)
  481.     system_use_pos++;
  482.   system_use_pos += p_skip_size;
  483.  
  484.   /* the system use field must be at least 4 bytes long */
  485.   while (system_use_pos + 3 < length) {
  486.     slen = buf[system_use_pos+2];
  487.     /* look for continuation area: */
  488.     if (buf[system_use_pos] == 'C' &&
  489.         buf[system_use_pos+1] == 'E') {
  490.       unsigned long newloc, offset;
  491.       printf ("/ ");
  492.       memcpy (&newloc, buf + system_use_pos + 8, 4);
  493.       memcpy (&offset, buf + system_use_pos + 16, 4);
  494.       memcpy (&length, buf + system_use_pos + 24, 4);
  495.       if (!Read_Sector (p_cd, newloc))
  496.         return;
  497.       buf = p_cd->buffer;
  498.       system_use_pos = offset;
  499.       continue;
  500.     /* look for system use field terminator: */
  501.     } else if (buf[system_use_pos] == 'S' &&
  502.         buf[system_use_pos+1] == 'T')
  503.       return;
  504.     else {
  505.       putchar (buf[system_use_pos]);
  506.       putchar (buf[system_use_pos+1]);
  507.       putchar (' ');
  508.     }
  509.  
  510.     system_use_pos += slen;
  511.   }
  512.   
  513.   putchar ('\n');
  514. }
  515.  
  516. void Show_Subdirectory (CDROM_OBJ *p_home, char *p_name, int p_long_info,
  517.             int p_recursive)
  518. {
  519.   CDROM_OBJ *obj;
  520.   CDROM_INFO info;
  521.   VOLUME *vol = p_home->volume;
  522.  
  523.   if (obj = Open_Object (p_home, p_name)) {
  524.     unsigned long offset = 0;
  525.     
  526.     while (Examine_Next (obj, &info, &offset)) {
  527.       directory_record *dir = info.suppl_info;
  528.       fwrite (info.name, info.name_length, 1, stdout);
  529.       if (info.directory_f)
  530.         printf (" (dir)");
  531.       printf ("\n");
  532.       if (p_long_info && dir) {
  533.         printf ("   %02d.%02d.%02d %02d:%02d:%02d  ",
  534.         (int) dir->day,
  535.         (int) dir->month,
  536.         (int) dir->year,
  537.         (int) dir->hour,
  538.         (int) dir->minute,
  539.         (int) dir->second);
  540.     printf ("%lu  ", dir->data_length_m);
  541.     Show_Flags (dir->flags);
  542.     putchar ('\n');
  543.         if (dir->ext_attr_length)
  544.       printf ("   contains extended attribute record\n");
  545.     if (dir->gap_size)
  546.       printf ("   is recorded in interleaved mode\n");
  547.     if (vol->protocol == PRO_ROCK)
  548.           Print_System_Use_Fields (vol->cd, dir,
  549.                      ((t_iso_vol_info *) vol->vol_info)->skip);
  550.       }
  551.     }
  552.  
  553.     Close_Object (obj);
  554.   } else {
  555.     fprintf (stderr, "Object '%s': iso_errno = %d\n", p_name, iso_errno);
  556.     return;
  557.   }
  558.  
  559.   if (p_recursive) {
  560.     if (obj = Open_Object (p_home, p_name)) {
  561.       unsigned long offset = 0;
  562.     
  563.       while (Examine_Next (obj, &info, &offset)) {
  564.         if (info.directory_f) {
  565.       char *name = malloc (strlen (p_name) + info.name_length + 2);
  566.       int len;
  567.       if (!name) {
  568.         fprintf (stderr, "out of memory\n");
  569.         exit (1);
  570.       }
  571.       if (Is_Top_Level_Object (obj))
  572.         name[0] = 0;
  573.       else
  574.         sprintf (name, "%s/", p_name);
  575.       len = strlen (name) + info.name_length;
  576.       memcpy (name + strlen (name), info.name, info.name_length);
  577.       name[len] = 0;
  578.       printf ("\n%s:\n", name);
  579.       Show_Subdirectory (p_home, name, p_long_info, TRUE);
  580.       free (name);
  581.         }
  582.       }
  583.       Close_Object (obj);
  584.     } else {
  585.       fprintf (stderr, "Object '%s': iso_errno = %d\n", p_name, iso_errno);
  586.     }
  587.   }
  588.  
  589. }
  590.  
  591. void Show_Dir_Contents (CDROM *p_cd, char *p_name, int p_rock_ridge,
  592.             char *p_options)
  593. {
  594.   VOLUME *vol;
  595.   CDROM_OBJ *home;
  596.   t_bool long_info = (strchr (p_options, 'l') != NULL);
  597.   t_bool recursive = (strchr (p_options, 'r') != NULL);
  598.  
  599.   if (!(vol = Open_Volume (p_cd, p_rock_ridge))) {
  600.     fprintf (stderr, "cannot open volume; iso_errno = %d\n", iso_errno);
  601.     exit (1);
  602.   }
  603.  
  604.   if (!(home = Open_Top_Level_Directory (vol))) {
  605.     fprintf (stderr, "cannot open top level directory;"
  606.                      " iso_errno = %d\n", iso_errno);
  607.     Close_Volume (vol);
  608.     exit (1);
  609.   }
  610.  
  611.   Show_Subdirectory (home, p_name, long_info, recursive);
  612.  
  613.   Close_Object (home);
  614.   Close_Volume (vol);
  615. }
  616.  
  617. void Send_Test_Unit_Ready (CDROM *p_cd)
  618. {
  619.   printf ("result = %d\n", Test_Unit_Ready (p_cd));
  620. }
  621.  
  622. void Show_Sectors (CDROM *p_cd, int p_sector, int p_cnt)
  623. {
  624.   int i, j, s;
  625.   int off;
  626.   
  627.   if (p_sector < 0)
  628.     return;
  629.   
  630.   for (s=0; s<p_cnt; s++) {
  631.     if (!Read_Sector (p_cd, p_sector + s)) {
  632.       fprintf (stderr, "cannot read sector %d\n", p_sector + s);
  633.       exit (1);
  634.     }
  635.     for (off=0, i=0; i<128; i++) {
  636.       printf ("%02x:%03x0: ", s, i);
  637.       for (j=0; j<16; j++)
  638.         printf ("%02x ", (int) p_cd->buffer[off++]);
  639.       off -= 16;
  640.       putchar (' ');
  641.       for (j=0; j<16; j++) {
  642.         char c = p_cd->buffer[off++];
  643.         if (32<=c && c<=127)
  644.           putchar (c);
  645.         else
  646.           putchar ('.');
  647.       }
  648.       putchar ('\n');
  649.     }
  650.   }
  651. }
  652.  
  653. int Get_Device_And_Unit (void)
  654. {
  655.   int len;
  656.   char buf[10];
  657.   
  658.   len = GetVar ((UBYTE *) "CDROM_DEVICE", (UBYTE *) g_the_device,
  659.           sizeof (g_the_device), 0);
  660.   if (len < 0)
  661.     return 0;
  662.   if (len >= sizeof (g_the_device)) {
  663.     fprintf (stderr, "CDROM_DEVICE too long\n");
  664.     exit (1);
  665.   }
  666.   g_the_device[len] = 0;
  667.   
  668.   len = GetVar ((UBYTE *) "CDROM_UNIT", (UBYTE *) buf,
  669.           sizeof (buf), 0);
  670.   if (len < 0)
  671.     return 0;
  672.   if (len >= sizeof (buf)) {
  673.     fprintf (stderr, "CDROM_UNIT too long\n");
  674.     exit (1);
  675.   }
  676.   buf[len] = 0;
  677.   g_the_unit = atoi (buf);
  678.   
  679.   if (GetVar ((UBYTE *) "CDROM_TRACKDISK", (UBYTE *) buf,
  680.       sizeof (buf), 0) > 0) {
  681.     fprintf (stderr, "using trackdisk\n");
  682.     g_trackdisk = 1;
  683.   }
  684.  
  685.   if (GetVar ((UBYTE *) "CDROM_FASTMEM", (UBYTE *) buf,
  686.       sizeof (buf), 0) > 0) {
  687.     fprintf (stderr, "using fastmem\n");
  688.     g_fastmem = 1;
  689.   }
  690.  
  691.   return 1;
  692. }
  693.  
  694. void Select_Mode (CDROM *p_cd, int p_mode)
  695. {
  696.   if (!Select_XA_Mode (p_cd, p_mode))
  697.     fprintf (stderr, "mode select command failed!\n");
  698. }
  699.  
  700. void Show_Drive_Information (CDROM *p_cd)
  701. {
  702.   t_inquiry_data data;
  703.   
  704.   if (!Inquire (p_cd, &data)) {
  705.     fprintf (stderr, "cannot access CDROM drive\n");
  706.     return;
  707.   }
  708.  
  709.   if ((data.peripheral_type & 0x1f) != 5) {
  710.     if ((data.peripheral_type & 0x1f) == 8)
  711.       printf ("Drive type: medium changer\n");
  712.     else
  713.       printf ("WARNING: this is not a CDROM drive!\n");
  714.   }
  715.  
  716.   printf ("Vendor  : ");
  717.   fwrite (data.vendor, sizeof (data.vendor), 1, stdout);
  718.   printf ("\nProduct : ");
  719.   fwrite (data.product, sizeof (data.product), 1, stdout);
  720.   printf ("\nRevision: ");
  721.   fwrite (data.revision, sizeof (data.revision), 1, stdout);
  722.   putchar ('\n');
  723. }
  724.  
  725. void Show_Table_Of_Contents (CDROM *p_cd)
  726. {
  727.   t_toc_header hdr;
  728.   t_toc_data *toc;
  729.   short i, len;
  730.   
  731.   if (!(toc = Read_TOC (p_cd, &hdr))) {
  732.     fprintf (stderr, "cannot read table of contents\n");
  733.     return;
  734.   }
  735.   
  736.   len = hdr.length / 8;
  737.   for (i=0; i<len; i++) {
  738.     if (toc[i].track_number == 0xAA)
  739.       printf ("Lead-out track at address %lu\n", toc[i].address);
  740.     else
  741.       printf ("Track %d: %s track, start address %lu\n",
  742.               (int) toc[i].track_number,
  743.           (toc[i].flags & 4) ? "data" : "audio",
  744.           toc[i].address);
  745.   }
  746. }
  747.  
  748. void Show_Catalog_Node (CDROM *p_cd, t_ulong p_node)
  749. {
  750.   t_mdb mdb;
  751.   t_node_descr *node;
  752.   t_hdr_node *hdr;
  753.   t_idx_record *idx;
  754.   t_leaf_record *leaf;
  755.   t_file_record *file;
  756.   t_dir_thread_record *thread;
  757.   char *cp;
  758.   int blk;
  759.   int i;
  760.   char buf[100];
  761.  
  762.   blk = HFS_Find_Master_Directory_Block (p_cd, &mdb);
  763.   if (blk < 0) {
  764.     fprintf (stderr, "cannot find master directory block\n");
  765.     return;
  766.   }
  767.  
  768.   node = HFS_Get_Node (p_cd, blk, &mdb, p_node);
  769.   if (!node) {
  770.     fprintf (stderr, "cannot find node %d\n", p_node);
  771.     return;
  772.   }
  773.   
  774.   switch (node->Type) {
  775.   case 0:
  776.     printf ("Index node:\n");
  777.     printf ("Fwd=%lu Bwd=%lu Level=%d\n", node->FLink, node->BLink,
  778.             (int) node->NHeight);
  779.     idx = (t_idx_record *) ((char *) node + 0xe);
  780.     for (i=0; i<node->NRecs; i++, idx++) {
  781.       printf ("Parent ID = 0x%08lx, '", idx->parent_id);
  782.       fwrite (idx->name, idx->name_length, 1, stdout);
  783.       printf ("', pointer = %lu\n", idx->pointer);
  784.     }
  785.     break;
  786.   case 1:
  787.     printf ("Header node:\n");
  788.     printf ("Fwd=%lu Bwd=%lu Level=%d\n", node->FLink, node->BLink,
  789.             (int) node->NHeight);
  790.     hdr = (t_hdr_node *) node;
  791.     printf ("Depth of tree:                  %u\n", hdr->Depth);
  792.     printf ("Number of root node:            %lu\n", hdr->Root);
  793.     printf ("Number of leaf records in tree: %lu\n", hdr->NRecs);
  794.     printf ("Number of first leaf node:      %lu\n", hdr->FNode);
  795.     printf ("Number of last leaf node:       %lu\n", hdr->LNode);
  796.     break;
  797.   case 2:
  798.     printf ("Map node:\n");
  799.     printf ("Fwd=%lu Bwd=%lu Level=%d\n", node->FLink, node->BLink,
  800.             (int) node->NHeight);
  801.     break;
  802.   case 0xff:
  803.     printf ("Leaf node:\n");
  804.     printf ("Fwd=%lu Bwd=%lu Level=%d\n", node->FLink, node->BLink,
  805.             (int) node->NHeight);
  806.     for (i=0; i<node->NRecs; i++) {
  807.       leaf = (t_leaf_record *) ((char *) node + ((short *) node)[255-i]);
  808.       cp = (char *) leaf + leaf->length + 1;
  809.       if ((leaf->length & 1) == 0)
  810.         cp++;
  811.       printf ("Parent ID = 0x%08lx, '", leaf->parent_id);
  812.       memcpy (buf, leaf->name, leaf->name_length);
  813.       Convert_Mac_Characters (buf, leaf->name_length);
  814.       fwrite (buf, leaf->name_length, 1, stdout);
  815.       printf ("'  (");
  816.       switch (*cp) {
  817.       case 1:
  818.         printf ("directory 0x%08lx)\n", *(t_ulong *)(cp+6));
  819.     break;
  820.       case 2:
  821.         file = (t_file_record *) cp;
  822.         printf ("file 0x%08lx)\n\tdata length %lu, "
  823.         "data extents %u-%u/%u-%u/%u-%u\n",
  824.         file->FlNum,
  825.         file->LgLen,
  826.         file->ExtRec[0].StABN, file->ExtRec[0].NumABlks,
  827.         file->ExtRec[1].StABN, file->ExtRec[1].NumABlks,
  828.         file->ExtRec[2].StABN, file->ExtRec[2].NumABlks);
  829.     printf ("\tresource length %lu, resource extents %u-%u/%u-%u/%u-%u\n",
  830.         file->RLgLen,
  831.         file->RExtRec[0].StABN, file->RExtRec[0].NumABlks,
  832.         file->RExtRec[1].StABN, file->RExtRec[1].NumABlks,
  833.         file->RExtRec[2].StABN, file->RExtRec[2].NumABlks);
  834.     printf ("\tfirst alloc blk for data fork: %u\n", file->StBlk);
  835.     printf ("\tfirst alloc blk for resource fork: %u\n", file->RStBlk);
  836.     break;
  837.       case 3:
  838.         thread = (t_dir_thread_record *) cp;
  839.         printf ("directory thread 0x%08lu '", thread->ParID);
  840.     fwrite (thread->CName, thread->CNameLen, 1, stdout);
  841.     printf ("')\n");
  842.     break;
  843.       case 4:
  844.         printf ("file thread)\n");
  845.     break;
  846.       default:
  847.         printf ("unknown)\n");
  848.     break;
  849.       }
  850.     }
  851.     break;
  852.   default:
  853.     printf ("unknown node type\n");
  854.     return;
  855.   }
  856.  
  857. }
  858.  
  859. void Play_Audio (CDROM *p_cd, int p_stop)
  860. {
  861.   int result;
  862.  
  863.   if (p_stop)
  864.     result = Stop_Play_Audio (p_cd);
  865.   else
  866.     result = Start_Play_Audio (p_cd);
  867.   
  868.   if (!result)
  869.     fprintf (stderr, "cannot perform operation\n");
  870. }
  871.  
  872. void main (int argc, char *argv[])
  873. {
  874.   atexit (Cleanup);
  875.  
  876.   if (argc < 2)
  877.     Usage ();
  878.  
  879.   if (!(UtilityBase = (struct Library *)
  880.          OpenLibrary ((UBYTE *) "utility.library", 37))) {
  881.     fprintf (stderr, "cannot open utility.library\n");
  882.     exit (1);
  883.   }
  884.  
  885.   if (!Get_Device_And_Unit ()) {
  886.     fprintf (stderr,
  887.       "Please set the following environment variables:\n"
  888.       "  CDROM_DEVICE    name of SCSI device\n"
  889.       "  CDROM_UNIT      unit number of CDROM drive\n"
  890.       "e.g.\n"
  891.       "  setenv CDROM_DEVICE scsi.device\n"
  892.       "  setenv CDROM_UNIT 2\n"
  893.       "Set the variable CDROM_TRACKDISK to any value if you\n"
  894.       "want to use trackdisk calls instead of SCSI-direct calls\n"
  895.       "Set the variable CDROM_FASTMEM to any value if you\n"
  896.       "want to use fast memory for SCSI buffers (does not work\n"
  897.       "with all SCSI devices!)\n"
  898.       );
  899.     exit (1);
  900.   }
  901.  
  902.   cd = Open_CDROM (g_the_device, g_the_unit, g_trackdisk, g_fastmem,
  903.              STD_BUFFERS, FILE_BUFFERS);
  904.   if (!cd) {
  905.     fprintf (stderr, "cannot open CDROM\n");
  906.     exit (1);
  907.   }
  908.  
  909.   if (argv[1][0] == 'a' && argc == 2)
  910.     Show_Drive_Information (cd);
  911.   else if (argv[1][0] == 'b' && argc == 2)
  912.     Show_Table_Of_Contents (cd);
  913.   else if (argv[1][0] == 'c' && argc == 3)
  914.     Show_File_Contents (cd, argv[2]);
  915.   else if (argv[1][0] == 'd' && argc == 3)
  916.     Show_Dir_Contents (cd, argv[2], 0, argv[1]+1);
  917.   else if (argv[1][0] == 'e' && argc == 3)
  918.     Show_Dir_Contents (cd, argv[2], 1, argv[1]+1);
  919.   else if (argv[1][0] == 'f' && argc == 4)
  920.     Try_To_Open (cd, argv[2], argv[3]);
  921.   else if (argv[1][0] == 'i')
  922.     Check_Protocol (cd);
  923.   else if (argv[1][0] == 'j' && argc == 3)
  924.     Play_Audio (cd, atoi (argv[2]));
  925.   else if (argv[1][0] == 'm' && argc == 3)
  926.     Show_Catalog_Node (cd, atoi (argv[2]));
  927.   else if (argv[1][0] == 'o' && argc == 3)
  928.     Try_To_Open (cd, NULL, argv[2]);
  929.   else if (argv[1][0] == 'r')
  930.     Show_Root_Directory (cd);
  931.   else if (argv[1][0] == 's' && argc == 3)
  932.     Show_Sectors (cd, atoi (argv[2]), 1);
  933.   else if (argv[1][0] == 's' && argc == 4)
  934.     Show_Sectors (cd, atoi (argv[2]), atoi (argv[3]));
  935.   else if (argv[1][0] == 't' && argc == 3)
  936.     Try_To_Open (cd, (char *) -1, argv[2]);
  937.   else if (argv[1][0] == 'v')
  938.     Show_Primary_Volume_Descriptor (cd);
  939.   else if (argv[1][0] == 'x' && argc == 3)
  940.     Select_Mode (cd, atoi (argv[2]));
  941.   else if (argv[1][0] == 'y' && argc == 3)
  942.     Find_Block_Starting_With (cd, atoi (argv[2]));
  943.   else if (argv[1][0] == 'z')
  944.     Send_Test_Unit_Ready (cd);
  945.   else
  946.     Usage ();
  947.  
  948.   exit (0);
  949. }
  950.